package upm.etsit.gsi.lejos.mazesolver.behaviours;
import java.util.ArrayList;

/** Mapea todo el camino que hace el robot
 *
 * @author jrubia
 */
public class Mapper {

    /**
     * Lista donde mete todas las coordenadas, en foormato String(X,Y). El robot empieza en 0,0
     */
    private ArrayList<String> map;
    /**
     * Dirección en la que se mueve el robot, tomando los siguientes valores:
     * 0 - Avanza en sentido POSITIVO del eje X.
     * 1 - Avanza en sentido POSITIVO del eje Y.
     * 2 - Avanza en sentido NEGATIVO del eje X.
     * 3 - Avanza en sentido NEGATIVO del eje Y.
     */
    private int direction;
    /**
     * Coordenada X en la que está el robot.
     */
    private int x;
    /**
     * Coordenada Y en la que está el robot.
     */
    private int y;

    /**
     * Constructor sin parámetros, la dirección inicial es 0.
     */
    public Mapper() {
        this.direction = 0;
        this.x = 0;
        this.y = 0;
        this.map = new ArrayList<String>();
    }

    /**
     * @return the mapa
     */
    public ArrayList<String> getMapa() {
        return map;
    }

    /**
     * @param mapa the mapa to set
     */
    public void setMap(ArrayList<String> map) {
        this.setMap(map);
    }

    /**
     * @return the direction
     */
    public int getDirection() {
        return direction;
    }

    /**
     * @param direction the direction to set
     */
    public void setDirection(int direction) {
        this.direction = direction;
    }

    /**
     * @return the x
     */
    public int getX() {
        return x;
    }

    /**
     * @param x the x to set
     */
    public void setX(int x) {
        this.x = x;
    }

    /**
     * @return the y
     */
    public int getY() {
        return y;
    }

    /**
     * @param y the y to set
     */
    public void setY(int y) {
        this.y = y;
    }

    /**
     * Cambia la dirección del robot, en función de hacia donde gire el robot, pero siempre tiene que girar en ángulos rectos.
     * 90 - Giro a la izquierda.
     * -90 - Giro a la derecha.
     *
     * @param giro
     */
    public void rotate(int rotation) {
        switch (rotation) {
            case 90:
                if (this.getDirection() < 3) {
                    this.setDirection(this.getDirection() + 1);
                } else {
                    this.setDirection(0);
                }
                break;
            case -90:
                if (this.getDirection() > 0) {
                    this.setDirection(this.getDirection() - 1);
                } else {
                    this.setDirection(3);
                }
                break;
        }
    }

    /**
     * Método interno para pasar rápidamente de coordenadas en dos Integer a una String
     * @param x
     * @param y
     * @return Las coordenadas en formato String(X,Y)
     */
    private String coordToString(int x, int y) {
        return "" + x + "," + y;
    }

    /**
     * Añade la posición en la que se encuentra a la lista de coordenadas
     */
    public void map() {
        this.map.add(coordToString(this.x, this.y));
    }

    /**
     * Comprueba si el robot ya ha estado en las coordendas en las que se encuentra
     * @return True si ya ha estado, False en caso contrario
     */
    public Boolean testAlreadyStay(int x, int y) {
        for (String coordenates : this.map) {
            if (coordenates.equals(coordToString(x, y))) {
                return true;
            }
        }
        return false;
    }

    /**
     * Avanza una unidad en la dirección y sentido que marca el atributo direction.
     */
    public void advance() {
        switch (this.direction) {
            case 0:
                this.x++;
                break;
            case 1:
                this.y++;
                break;
            case 2:
                this.x--;
                break;
            case 3:
                this.y--;
                break;
        }

    }

    public boolean pasadoSiguiente() {

         switch (this.direction) {
            case 0:
                if (testAlreadyStay(getX() + 1, getY())) {
                    return true;
                } else {
                    return false;
                }
            case 1:
                if (testAlreadyStay(getX(), getY() + 1)) {
                    return true;
                } else {
                    return false;
                }
            case 2:
                if (testAlreadyStay(getX() - 1, getY())) {
                    return true;
                } else {
                    return false;
                }
            case 3:
                if (testAlreadyStay(getX(), getY() - 1)) {
                    return true;
                } else {
                    return false;
                }
        }

         return false;
    }
}
